package org.erepublik.company.product;

import java.text.DecimalFormat;

import org.erepublik.company.Company;
import org.erepublik.company.ECountry;
import org.erepublik.company.EProductType;
import org.erepublik.company.JSONAble;
import org.erepublik.company.generated.CustomizationT;
import org.erepublik.company.generated.OfferT;

/**
 * Klasa reprezentujaca oferte dostepna na rynku
 *
 * @author Kacper Gorski 'Railman' railman85@gmail.com
 */
public abstract class Product implements Comparable<Product>,Cloneable, JSONAble {

	private Company companyOwner; // id firmy oferujacej

	private double price; // cena w lokalnej walucie
	private double priceInGold;
	private ECountry market; // kraj, w ktorym produkt jesty wystawiony
	private EProductType productType; 
	private ProductDesign productDesign;
	private int quantity; // ilosc produktow wystawionych w ofercie
	
	/**
	 * Tworzy oferte wraz z domyslnym designem (wszystkei atrybuty wyzerowane)
	 * @param productType
	 */
	public Product(EProductType productType) {
		setProductDesign( new ProductDesign(productType) );
		this.productType = productType;
	}
	
	public Company getCompanyOwner() {
		return companyOwner;
	}

	public void setCompanyOwner(Company companyOwner) {
		this.companyOwner = companyOwner;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}


	
	public ECountry getCountry() {
		return market;
	}

	public void setMarket(ECountry market) {
		this.market = market;
	}

	public EProductType getProductType() {
		return productType;
	}

	public void setProductType(EProductType productType) {
		this.productType = productType;
//		if (productType.isRaw())
//			setQuality(EQuality.Q1);
	}

	public ProductDesign getProductDesign() {
		return productDesign;
	}

	public void setProductDesign(ProductDesign productDesign) {
		this.productDesign = productDesign;
	}

	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	public int getQuantity() {
		return quantity;
	}

	public int compareTo(Product o) {
		double roznica = o.getPrice() - getPrice();
		if (roznica>0.0)
			return -1;
		if (roznica<0.0)
			return 1;
		return o.getQuantity() - getQuantity(); // alternatywnie sortujemy po ilosci towaru
	}


	public void setProductDesign(OfferT offer) {
		EProductAttribute[] attributes = EProductAttribute.getAllAttributes(productType);
		for (int i=0; i < attributes.length; i++) {
			int attributeValue = getAttributeValue(attributes[i], offer.getCustomization());
			productDesign.setAttributeValue(attributes[i], attributeValue);
		}
	}

	private int getAttributeValue(EProductAttribute productAttribute, CustomizationT offer) {
		if (productAttribute == EProductAttribute.AREA_OF_EFFECT)
			return offer.getAreaOfEffect();
		if (productAttribute == EProductAttribute.ATTACK)
			return offer.getAttack();
		if (productAttribute == EProductAttribute.DAMAGE)
			return offer.getAttack();
		if (productAttribute == EProductAttribute.DEFENSE)
			return offer.getDefense();
		if (productAttribute == EProductAttribute.DURABILITY && offer.getDefense()==null)
			return offer.getHappiness();
		if (productAttribute == EProductAttribute.DURABILITY && offer.getDefense()!=null)
			return offer.getDefense();
		if (productAttribute == EProductAttribute.HAPPINESS)
			return offer.getHappiness();
		if (productAttribute == EProductAttribute.MOVING_DISTANCE)
			return offer.getHappiness();		
		if (productAttribute == EProductAttribute.WELLNESS)
			return offer.getWellness();	
		
		throw new IllegalArgumentException("Brak obslugi atrybutu produktu "+productAttribute);
	}

	public void setPriceInGold(double priceInGold) {
		this.priceInGold = priceInGold;
	}

	public double getPriceInGold() {
		return Math.round(priceInGold*100000.0)/100000.0d;
	}
	
	public String getPriceInGoldFormatted() {
	    DecimalFormat decimalFormatter = new DecimalFormat("##0.0######");
	    return decimalFormatter.format( getPriceInGold() );
	}

	
	public Product clone() {
	    try {
            return (Product) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return null;
        }
	}
}
